package stub;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;

import messages.BaseMessage;
import messages.GeneralAck;
import messages.MessageFactory;
import messages.MessageType;
import messages.udp.PersonInElevatorMessage;
import messages.udp.PersonOutElevatorMessage;
import messages.udp.PersonPressButtonMessage;
import messages.udp.PersonTransferMessage;

public class PDispatcherStub {
	private DatagramSocket dSocket;
	private InetAddress elevatorAddress;
	private int elevatorPort;

	private int myPort = 12000;
	
	public PDispatcherStub(){
		
	}

	public void startSocket(InetAddress host,int port){
		try {
			dSocket=new DatagramSocket(myPort);
		} catch (SocketException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		elevatorAddress=host;
		elevatorPort=port;
		
		dSocket.connect(host, port);
	}
	
	//Close the socket (Although it doesn't truly exist)
	public void endSocket(){
		dSocket.close();
	}
	
	//Send person transfer (1 = in, 0 = out)
	//Expect an ack, with a personTransfer message type
	//Return values:
	// -1 = Not general Ack
	// -2 = General ack, but not for person transfer
	//  0 = General Ack, but fail
	//  1 = General Ack and success
	public int sendPersonTransfer(int weight, byte inOut){
		DatagramPacket d;
		byte[] buf = new byte[255]; 
		BaseMessage bm;
		GeneralAck ack;
		
		//Create the message
		PersonTransferMessage ptm = new PersonTransferMessage(inOut,weight);
		d = new DatagramPacket(ptm.toByteArray(),ptm.toByteArray().length);
		
		//Send the message
		try {
			d.setAddress(elevatorAddress);
			d.setPort(elevatorPort);
			dSocket.send(d);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		//Receive the ack
		d.setData(buf);
		try {
			dSocket.receive(d);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		//Check the contents
		bm = MessageFactory.parseMessage(d.getData());

		if (bm.getMessageType()==MessageType.GeneralAck){
			ack = (GeneralAck) bm;
			if (ack.getAckMessageType() == MessageType.PersonTransferMessage){
				if (ack.getSuccess()){
					return 1;
				}else{
					return 0;
				}
			}else{
				return -2;
			}
		}
		
		//If not a general ack, this failed
		return -1;
	}
	
	
	//Send person in elevator
	//Expect an ack with PersonInElevator message type
	//Return values:
	// -1 = Not general Ack
	// -2 = General ack, but not for person in
	//  0 = General Ack, but fail
	//  1 = General Ack and success
	public int sendPersonInElevator(){
		DatagramPacket d;
		byte[] buf = new byte[255]; 
		BaseMessage bm;
		GeneralAck ack;
		
		//Create the message
		PersonInElevatorMessage pie = new PersonInElevatorMessage();
		d = new DatagramPacket(pie.toByteArray(),pie.toByteArray().length);
		
		//Send the message
		try {
			d.setAddress(elevatorAddress);
			d.setPort(elevatorPort);
			dSocket.send(d);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		//Receive the ack
		d.setData(buf);
		try {
			dSocket.receive(d);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		//Check the contents
		bm = MessageFactory.parseMessage(d.getData());

		if (bm.getMessageType()==MessageType.GeneralAck){
			ack = (GeneralAck) bm;
			if(ack.getAckMessageType() == MessageType.PersonInElevatorMessage){
				if(ack.getSuccess()){
					return 1;
				}else{
					return 0;
				}
			}else{
				return -2;
			}
		}
		
		//If not a general ack, this failed
		return -1;
	}
	
	//send person out elevator
	//Expect an ack with PersonOutElevator message type
	//Return values:
	// -1 = Not general Ack
	// -2 = General ack, but not for person transfer
	//  0 = General Ack, but fail
	//  1 = General Ack and success
	public int sendPersonOutElevator(){
		DatagramPacket d;
		byte[] buf = new byte[255]; 
		BaseMessage bm;
		GeneralAck ack;
		
		//Create the message
		PersonOutElevatorMessage pie = new PersonOutElevatorMessage();
		d = new DatagramPacket(pie.toByteArray(),pie.toByteArray().length);
		
		//Send the message
		try {
			d.setAddress(elevatorAddress);
			d.setPort(elevatorPort);
			dSocket.send(d);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		//Receive the ack
		d.setData(buf);
		try {
			dSocket.receive(d);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		//Check the contents
		bm = MessageFactory.parseMessage(d.getData());

		if (bm.getMessageType()==MessageType.GeneralAck){
			ack = (GeneralAck) bm;
			if(ack.getAckMessageType() == MessageType.PersonOutElevatorMessage){
				if (ack.getSuccess()){
					return 1;
				}else{
					return 0;
				}
			}else{
				return -2;
			}
		}
		
		//If not a general ack, this failed
		return -1;
	}
	
	//send button press (floor)
	//Return values:
	// -1 = Fail (Not general ack)
	// -2 = Fail (Not ack for a PersonPressButtonMessage)
	//  1 = Button Valid
	//  2 = Button Invalid
	public int sendButtonPress(byte button){
		DatagramPacket d;
		byte[] buf = new byte[255]; 
		BaseMessage bm;
		GeneralAck ack;
		
		//Create the message
		PersonPressButtonMessage pbm = new PersonPressButtonMessage(button);
		buf = pbm.toByteArray();
		d = new DatagramPacket(buf,buf.length);
		
		//Send the message
		try {
			d.setAddress(elevatorAddress);
			d.setPort(elevatorPort);
			dSocket.send(d);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		//Receive the ack
		buf = new byte[255];
		d=new DatagramPacket(buf,buf.length);
		try {
			dSocket.receive(d);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		//Check the contents
		bm = MessageFactory.parseMessage(buf);
		if (bm.getMessageType()==MessageType.GeneralAck){
			ack = (GeneralAck) bm;
			if (ack.getAckMessageType() == MessageType.PersonPressButtonMessage){
				if (ack.getSuccess()){
					return 1;
				}else{
					return 2;
				}
			}else{
				return -2;
			}
		}
		
		//If not a general ack, this failed
		return -1;
	}
	
}
